package xin.marcher.module.common.redis;

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 *
 */
@Component
public class RedisBloom {

    /**
     * 默认初始大小
     */
    public static int defaultInitialSize = 50000;

    /**
     * 默认错误率
     */
    public static double defaultErrorRate = 0.01;

    private final Map<String, RBloomFilter> bloomFilterMap = new ConcurrentHashMap<>();

    private RedissonClient redissonClient;

    public RedisBloom(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    /**
     * 获取布隆过滤器，如果不存在，则创建并添加初始数据
     *
     * @param filterKey
     * @param getInitBloomValue
     * @param bloomField
     * @return
     */
    public RBloomFilter getBloomFilter(String filterKey, Function<String, Optional<List<String>>> getInitBloomValue,
                                       String bloomField) {
        Assert.hasLength(filterKey, "bloom filter key must not be null");

        // 布隆过滤器key加锁，防止同一个布隆过滤器重复创建
        synchronized (filterKey.intern()) {
            RBloomFilter bloomFilter = bloomFilterMap.get(filterKey);
            // 如果当前key的过滤器没有还未创建，则创建并初始化
            if (bloomFilter == null) {
                bloomFilter = redissonClient.getBloomFilter(filterKey);
                bloomFilter.tryInit(defaultInitialSize, defaultErrorRate);
                Optional<List<String>> optional = getInitBloomValue.apply(bloomField);
                if (optional.isPresent()) {
                    // 添加初始数据
                    for (String str : optional.get()) {
                        bloomFilter.add(str);
                    }
                }
                bloomFilterMap.put(filterKey, bloomFilter);
            }
            return bloomFilter;
        }

    }

    /**
     * 指定布隆过滤器添加值
     *
     * @param filterKey
     * @param value
     * @param getInitBloomValue
     * @param bloomField
     * @return
     */
    public Boolean add(String filterKey, Object value, Function<String, Optional<List<String>>> getInitBloomValue, String bloomField) {
        // Assert.hasLength(filterKey, "bloom filter key must not be null");
        // RBloomFilter bloomFilter = getBloomFilter(filterKey, getInitBloomValue, bloomField);
        // return bloomFilter.add(value);
        return true;
    }

    /**
     * 判断指定布隆过滤器是否包含值
     *
     * @param filterKey
     * @param value
     * @param getInitBloomValue
     * @param bloomField
     * @return
     */
    public Boolean contains(String filterKey, Object value,
                            Function<String, Optional<List<String>>> getInitBloomValue, String bloomField) {
        // Assert.hasLength(filterKey, "bloom filter key must not be null");
        // return getBloomFilter(filterKey, getInitBloomValue, bloomField).contains(value);
        return true;
    }

}